/**
 * 
 */
package com.ideeli.webextractor.service;

import static com.ideeli.webextractor.utils.Constants.IT_FTP_PASS;
import static com.ideeli.webextractor.utils.Constants.IT_FTP_SERVER;
import static com.ideeli.webextractor.utils.Constants.IT_FTP_USER;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.ideeli.webextractor.context.StaticContext;
import com.ideeli.webextractor.dao.ProductDao;

/**
 * @author sa
 * 
 */
public class ProductImageServiceImpl implements ProductImageService
{
	private static final Logger logger = Logger.getLogger(ProductImageServiceImpl.class);

	private CacheService cacheService;
	private ProductDao productDao;
	
	FTPClient ftpClient = null;
	
	
	private boolean initConnection() throws Exception
	{
		String server = cacheService.getAppProperty(IT_FTP_SERVER);
		String user = cacheService.getAppProperty(IT_FTP_USER);
		String pass = cacheService.getAppProperty(IT_FTP_PASS);
		
		
		ftpClient = new FTPClient();
		
		ftpClient.connect(server);
		logger.warn("Connected to " + server + ".");
		logger.warn(ftpClient.getReplyString());

		// After connection attempt, you should check the reply code to
		// verify
		// success.
		int reply = ftpClient.getReplyCode();

		if (!FTPReply.isPositiveCompletion(reply))
		{
			ftpClient.disconnect();
			logger.error("FTP server refused connection.");
			return false;
		}
		
		boolean isSuccess = ftpClient.login(user, pass);
		if (!isSuccess)
		{
			logger.error("FTP login unsuccessful.." + isSuccess);
			disconnectFTP();
		}

		logger.warn("FTP login successful.." + isSuccess);
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		logger.warn("FTP setfile type bin");
		
		logger.warn("FTP successfully initialized !!!!!!!");

		return true;
	}
	

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ideeli.webextractor.service.ProductImageService#synchronizeImages()
	 */
	@Override
	public void synchronizeImages() throws Exception
	{
		logger.warn("synchronizeImages");
		
		if(StaticContext.getStaticContext().isHomeRun())
		{
			logger.warn("synchronizeImages mocked.. home run");
			return;
		}
		
		
		
		if(ftpClient==null || !ftpClient.isConnected())
		{
			if(!initConnection())
			{
				logger.error("Connection unsuccessfull no further operation");
				return;
			}
		}
		
	
		try
		{
			    List<String> tmp=productDao.getImageNamesDB();
			    List<String> imagesInDb=new ArrayList<String>();
			    for(String image: tmp)
			    {
			    	imagesInDb.add(image.replaceAll("data/images/large/", ""));
			    }
			
			    deleteServerFiles(imagesInDb);
			    deleteLocalFiles(imagesInDb);
			    uploadFileFromLocal(imagesInDb);
			    logger.warn("Total image files in DB:"+tmp.size() );

				
		}
		catch (IOException e)
		{
			logger.error(e);
		}
		finally
		{
			disconnectFTP();
		}

		logger.warn("FTP complete..");

	}
	
	private void deleteServerFiles(List<String> imagesInDb) throws Exception
	{
		
//		String pathsToDeleteFiles[]={"public_html/image/data/images/large","public_html/image/cache/data/images/large"};

			ftpClient.changeWorkingDirectory("public_html/image/data/images/large");
			
			int i=1;
			FTPFile[] serverFiles=ftpClient.listFiles();
			for(FTPFile serverFile: serverFiles)
			{
				if(!imagesInDb.contains(serverFile.getName()))
				{
					boolean isDel=ftpClient.deleteFile(serverFile.getName());
					logger.warn(i++ +" Delete Server file:"+serverFile.getName()+" "+isDel);
				}
			}
			
			logger.warn("Total image files on Server:"+serverFiles.length );
		
		
	}

	
	private void deleteLocalFiles(List<String> imagesInDb) throws Exception
	{
		File dir=new File(cacheService.getActualImagePath());
		File[] files=dir.listFiles();
		int i=0;
		for(File f: files)
		{
			if(!imagesInDb.contains(f.getName()))
			{
				boolean isDel=f.delete();
				logger.warn(i++ +" Delete Local file:"+f.getName()+" "+isDel);
			}
		}
		logger.warn("Total image files on localo:"+files.length);
	}
	
	public void uploadFileFromLocal(List<String> imagesInDb) throws Exception
	{
		ftpClient.changeWorkingDirectory("public_html/image/data/images/large");
		List<String> serverFs= new ArrayList<String>();
		FTPFile[] serverFiles=ftpClient.listFiles();
		for(FTPFile f: serverFiles)
				serverFs.add(f.getName());
		
		
		File dir=new File(cacheService.getActualImagePath());
		File[] files=dir.listFiles();
		int i=1;
		for(File f: files)
		{
			if(imagesInDb.contains(f.getName()) && !serverFs.contains(f.getName()))
			{
				FileInputStream fIn=new FileInputStream(f);
				boolean isStored=ftpClient.storeFile(f.getName(), fIn);
				logger.warn(i++ +" File sent:"+isStored);
				fIn.close();
			}
//			logger.warn(f.getName());
		}
		
	}
	
	
	
	
	public void uploadFileFromStream() throws Exception
	{
		URL url = new URL("https://inquirecontent2.ingrammicro.com/images/300/1019286082.jpg");
		InputStream is = url.openStream();

		boolean isStored=ftpClient.storeFile("1000230.jpg", is);
		logger.warn("File sent:"+isStored);
		is.close();
	}
	
	private void disconnectFTP() 
	{
		if (ftpClient.isConnected())
		{
			try
			{
				ftpClient.logout();
				ftpClient.disconnect();
				ftpClient=null;
			}
			catch (IOException ioe)
			{
				logger.error(ioe);
			}
		}
	}

	public CacheService getCacheService()
	{
		return cacheService;
	}

	public void setCacheService(CacheService cacheService)
	{
		this.cacheService = cacheService;
	}


	public ProductDao getProductDao()
	{
		return productDao;
	}


	public void setProductDao(ProductDao productDao)
	{
		this.productDao = productDao;
	}

}
